﻿#include "mediaenc_hd.h"
 
#include <QCoreApplication>
#include <QPainter>
#include <QDateTime>
#include "mainwindow.h"
#include <QDebug>

extern "C"
{
#include "img_conv.h"
}

 #ifdef  LINUX_AARCH64
//
//                 *H.264 profile_idc parameter
//                 *66  - Baseline profile
//                 *77  - Main profile
//                 *100 - High profile
// mpp mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:profile", 66);
//42A01E --baseline
//
//64001f （High Profile + Level 3.1）
//640016 （High Profile + Level 2.2）
//640c34 （Constrained High Profile + Level 5.2）
//42801e （Baseline Profile + Level 3.0）



#include "im2d.h"
#include "RgaUtils.h"
#endif


MediaEncHD::MediaEncHD(QObject *parent,bool isRtsp)
{

   int i = 0;
   m_AppPath = QCoreApplication::applicationDirPath();

   m_parent = parent;

   m_nFps = 0;

  nRtspPort = 8554;

  m_pRGBFrame = new uint8_t[1920*1200*3];


   m_ThreadRun = true;

   memset(m_nRtspChn,0,sizeof (stEncRstpChn)*LD_RTSP_BUTT);

   memset(m_SpsPPS,0,256);

   m_isRtsp = isRtsp;

   if(isRtsp == true)
   {
        m_nRtspChn[LD_RTSP_MIX].nFps = 50;
        m_nRtspChn[LD_RTSP_MIX].nWidth = 1920;
        m_nRtspChn[LD_RTSP_MIX].nHeight = 1080;
        rtspInst = create_rtsp_demo(nRtspPort,40000);

        char cTmpURL[STR_BUFF_LEN+32] = {0};
        sprintf(cTmpURL,"/%s_%d",cRtspURL,i);
        m_nRtspChn[i].rtspSession = create_rtsp_session(rtspInst,cTmpURL,RTSP_CODEC_ID_VIDEO_H264);


#if  LINUX_AARCH64
     memset(&m_nRtspChn[i].mppEnc,0,sizeof(stEncCtx));
     encH265Init(&m_nRtspChn[i].mppEnc,0,
            m_nRtspChn[i].nWidth,
            m_nRtspChn[i].nHeight,
            MPP_FMT_RGB888,
            MPP_VIDEO_CodingAVC,
            m_nRtspChn[i].nFps,
            5,
            5000000,
            m_isRtsp);
#else
     memset(&m_nRtspChn[i].stFFMpegEncoder,0,sizeof(stFFMpegCtx));
     encFFMpegInit(&m_nRtspChn[i].stFFMpegEncoder,i,
            m_nRtspChn[i].nWidth,
            m_nRtspChn[i].nHeight,
            AV_PIX_FMT_RGB24,
            AV_CODEC_ID_H264,
            m_nRtspChn[i].nFps);
 #endif



   }
   else
   {
       m_nRtspChn[LD_RTSP_MIX].nFps = 50;
       m_nRtspChn[LD_RTSP_MIX].nWidth = 1920;
       m_nRtspChn[LD_RTSP_MIX].nHeight = 1080;

#if  LINUX_AARCH64
     memset(&m_nRtspChn[i].mppEnc,0,sizeof(stEncCtx));
     encH265Init(&m_nRtspChn[i].mppEnc,0,
            m_nRtspChn[i].nWidth,
            m_nRtspChn[i].nHeight,
            MPP_FMT_RGB888,
            MPP_VIDEO_CodingAVC,
            m_nRtspChn[i].nFps,
            5,
            5000000,
            m_isRtsp);
#else
     memset(&m_nRtspChn[i].stFFMpegEncoder,0,sizeof(stFFMpegCtx));
     encFFMpegInit(&m_nRtspChn[i].stFFMpegEncoder,i,
            m_nRtspChn[i].nWidth,
            m_nRtspChn[i].nHeight,
            AV_PIX_FMT_RGB24,
            AV_CODEC_ID_H264,
            m_nRtspChn[i].nFps);
 #endif


   }

   m_nRtspChn[LD_RTSP_MIX].nWidth  = 1920;
   m_nRtspChn[LD_RTSP_MIX].nHeight = 1080;




    pMainGUI = reinterpret_cast<MainWindow*>(m_parent);






    m_LostFrame = 0;
    m_IsVideoRec = false;
    m_IsRecSpsPPS = false;

    m_FrameCnt = 0;

    pH265Packet = (uint8_t*)malloc(FRAME_MAX_LEN/2);

    moveToThread(this);
}




MediaEncHD::~MediaEncHD()
{
    int i = 0;

    if(m_isRtsp)
    {
        if(m_nRtspChn[i].rtspSession) {
            rtsp_del_session(m_nRtspChn[i].rtspSession);
        }
        rtsp_del_demo(rtspInst);

    }

#ifdef  LINUX_AARCH64
        encH265Release(&m_nRtspChn[i].mppEnc);
#else
        encFFMpegRelease(&m_nRtspChn[i].stFFMpegEncoder);
#endif


    SAFE_DELETE_ARRAY(m_pRGBFrame);
    SAFE_DELETE_ARRAY(pH265Packet);

    log_i("~MediaEnc()");
}




void MediaEncHD::run()
{
   log_i("MediaEncHD rtsp  proc ok");
   exec();
   log_i("MediaEncHD rtsp proc is exit");
}

void MediaEncHD::Stop()
{
    quit();
}


void MediaEncHD::EncSendOneFrame(LD_RTSP_CHN rtspChn,uint8_t* pRGBFrame)
{
    int nPackLen = 0;
#ifdef  LINUX_AARCH64
    nPackLen = encH265Frame(&m_nRtspChn[rtspChn].mppEnc,pRGBFrame,pH265Packet);
#else
    nPackLen = encFFMpegPutFrame(&m_nRtspChn[rtspChn].stFFMpegEncoder,pImg,pH265Packet);
#endif

    if(nPackLen > 0)
    {
        //debug for write file
        //fwrite(pH265Packet,nPackLen,1,fp_output);

       if(m_isRtsp)
        {
            rtsp_sever_tx_video(rtspInst,
                   m_nRtspChn[rtspChn].rtspSession,
                   pH265Packet,nPackLen,
                   m_nRtspChn[rtspChn].nPts);
       }


        m_nRtspChn[rtspChn].nPts += 1000000/m_nRtspChn[rtspChn].nFps;
        m_nRtspChn[rtspChn].rtpPackSeq = m_nRtspChn[rtspChn].rtpPackSeq + 1;

        if(rtspChn == LD_RTSP_MIX)
        {
            m_nFps++;
        }
    }

}

void MediaEncHD::OnVideoRec(int startorstop,int nWidth,int nHeight)
{
    m_IsVideoRec = startorstop;
}


void MediaEncHD::EncHDFrame(LD_RTSP_CHN rtspChn,uint8_t* pImgData,int nWidth,int nHeight,int nErrCode)
{



    int   nPackLen = 0;
    int nLen = nWidth*nHeight*3;

    if(m_nRtspChn[rtspChn].nWidth != nWidth || m_nRtspChn[rtspChn].nHeight != nHeight)
    {
        //log_i("error , encoder thread rec chan %d width %d heigth %d error package",rtspChn,nWidth,nHeight);
        return;
    }

   // ldMemCpy(pImg,pImgData,nLen);

   #ifndef LINUX_AARCH64
   //================cpu versin rgb24 to yuv420p ============================


   #else
    //================rga version rgb 24 to yuv420p

    //========================================================================
   #endif

   if(m_IsRecSpsPPS)
   {

           if(m_nRtspChn[rtspChn].mppEnc.isGetSPS)
           {
             // m_pVideoRec->set_spspps(m_nRtspChn[rtspChn].mppEnc.ucSpsPpsBuf,m_nRtspChn[rtspChn].mppEnc.nSpsPpsLen);
              m_IsRecSpsPPS = true;
           }

   }

   if(nErrCode == LD_RES_CAMERA_ERR)
   {
       int i=0;
       for(i=0; i<60; i++)
       {//错误一秒检查到，错误不自动更新输出,给远端发20帧，远端好更新，太多没意义
          EncSendOneFrame(rtspChn,pImgData);
       }
   }
   else
   {

         EncSendOneFrame(rtspChn,pImgData);

   }

}


void MediaEncHD::ProcessFrame(stVFrame* frame)
{
    char cTextBuff[256] = {0};
    memcpy(m_pRGBFrame,frame->ucData,frame->nDataLen);
    QImage VisbileImg = QImage(m_pRGBFrame,frame->nWidth,frame->nHeight, QImage::Format_RGB888);
    QPainter painter(&VisbileImg);

    QFont font;
    font.setPixelSize(32);
    font.setBold(true);
    painter.setFont(font);
    painter.setPen(QPen(QColor(Qt::green)));

    QDateTime currentDateTime = QDateTime::currentDateTime();

    // 输出当前时间
    QString currentTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");

    sprintf(cTextBuff,"时间: %s 帧率: %d",currentTime.toStdString().c_str(),m_TmpFps);
    painter.drawText(8,64,cTextBuff);

    EncSendOneFrame(LD_RTSP_MIX,m_pRGBFrame);
}
